package tjs.styudy.mini.springboot.demo.transaction.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tjs.styudy.mini.springboot.transaction.aop.MiniTransactional;
import tjs.styudy.mini.springboot.transaction.aop.Propagation;
import tjs.styudy.mini.springboot.transaction.utils.JdbcTemplate;

import java.util.List;

/**
 * @author nicky
 * @date 2021/4/30 下午2:30
 */
@MiniTransactional
@Service
public class TransactionalService {
    @Autowired
    JdbcTemplate jdbcTemplate;
    @Autowired
    TransactionalService transactionalService;

    //@MiniTransactional(propagation = Propagation.REQUIRED)
    public void updateSonOfBalance(boolean isThrowException) {
        jdbcTemplate.execute("UPDATE user_test ut SET ut.balance = ut.balance + 1 WHERE ut.id = 1;");
        // 注入的bean，才能走代理
        transactionalService.updateFatherOfUserName(isThrowException);

        // 直接调用updateFatherOfUserName，updateFatherOfUserName是不会走代理的
        // 但是如果此前，已经绑定了已关闭自动提交的Connection到ThreadLocal，则即使没有走代理，也会是在同一事物下
        // this.updateFatherOfUserName(isThrowException);
        System.out.println("updateFatherOfUserName已执行完成，数据已入库。。。");
    }

    @MiniTransactional(propagation = Propagation.REQUIRES_NEW)//创建一个新事务，如果当前存在事务，将这个事务挂起
    public void updateFatherOfUserName(boolean isThrowException) {
        // 如果隔离级别为 Propagation.REQUIRES_NEW
        // 由于updateSonOfBalance修改了id为1的数据，但是并没有提交事务，此时id为1的那行数据仍旧在加锁状态，尚未释放
        // 此时再去修改id为1的数据，就会产生死锁。
        //jdbcTemplate.execute("UPDATE user_test ut SET ut.user_name = CONCAT(ut.user_name, \"_\", ut.balance+1)  WHERE ut.id = 1;");

        jdbcTemplate.execute("UPDATE user_test ut SET ut.user_name = CONCAT(ut.user_name, \"_\", ut.balance+1)  WHERE ut.id = 2;");
        if (isThrowException) {
            throw new RuntimeException("test rollback.....");
        }
    }

    public void find(String pre) {
        List<JSONObject> userTests = jdbcTemplate.query("select * from user_test ut where ut.id = 1;");
        System.out.println(pre + "：" + JSON.toJSONString(userTests));
    }
}
